
#pragma once

#include "tcp_socket.h"
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <unistd.h>
#include <map>

class LoopEvent;
class Channel;
class Connection;
class DataDecodec;

using ServerOnConnectFunc    = std::function<void(Connection * connection)>;
using ServerOnDisconnectFunc = std::function<void(Connection * connection)>;
using ServerOnMessageFunc    = std::function<void(Connection * connection, const uint8_t * data, int length)>;

class Server : std::enable_shared_from_this<Server>
{
public:
    Server(LoopEvent * loop);
    void Listen(int port);
public:
    void WriteCallback();
    void ProcessRead(int64_t channel_id);
    void ReadCallback(int64_t channel_id);
    void ErrorCallback(int64_t channel_id, int error_code);
public:
    void SetOnConnectionFunc(ServerOnConnectFunc && func);
    void SetOnMessageFunc(ServerOnMessageFunc    && func);
    void SetOnDisconnectionFunc(ServerOnDisconnectFunc && func);
private:
    TcpSocket m_socket;
    LoopEvent * m_loop;
private:
    std::shared_ptr<Channel> m_listen_channel;
    std::map<int64_t, Connection*> m_connection_map;
private:
    ServerOnConnectFunc m_connection_func;
    ServerOnMessageFunc m_message_func;
    ServerOnDisconnectFunc m_disconnection_func;
};